package com.zhitong.money.scheduleTasks;


import com.zhitong.money.entity.*;
import com.zhitong.money.mapper.*;
import com.zhitong.money.services.CheckService;
import com.zhitong.money.services.SalaryService;
import com.zhitong.money.services.api.IScheduleTimeService;
import com.zhitong.money.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Andy Zhang
 * @Description:
 * @Date: 10:02 2021/2/4
 * @Company: wisecard
 */
@Slf4j
@Configuration
@EnableScheduling   //开启定时任务
public class ScheduleTask implements SchedulingConfigurer {

    @Autowired
    private PositionMapper positionMapper;

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private CheckMapper checkMapper;

    @Autowired
    private SalaryService salaryService;

    @Autowired
    private CheckService checkService;

    @Autowired
    private LeaveMapper leaveMapper;

    @Autowired
    private HolidayMapper holidayMapper;

    @Autowired
    private PSalaryParamMapper paramMapper;

    @Autowired
    private KieBase kieBase;

    @Autowired
    private IScheduleTimeService scheduleTimeService;


    private String cron1 = "0 03 15 ? * MON-FRI";
    private String cron2 = "0 50 23 ? * MON-FRI";
    private String cron3 = "0 0 8 10 * ?";

    /**
     *@Author: AndyZhang
     *@Description 工作日的凌晨1点自动插入当天的考勤信息
     *@param
     *@return
     *@Date: 10:43 2021/2/4
     */
    public void startCheck(){
        //获得当天日历
        Calendar instance = Calendar.getInstance();
        instance.set(Calendar.HOUR_OF_DAY,0);
        instance.set(Calendar.MINUTE,0);
        instance.set(Calendar.SECOND,0);

        //查询条件
        Map<String,Object> map = new HashMap<>();
        map.put("date",DateUtil.dateToStr(instance.getTime(),DateUtil.FORMAT_DATE_CHECK));

        //是否为假期
        if (!isHoliday(instance)){
            List<String> subPids = positionMapper.findSubPids();
            List<String> tellIdsByPids = employeeMapper.findTellIdsByPids(subPids);
            if (tellIdsByPids!=null && !tellIdsByPids.isEmpty()){
                CheckTime checkTime =new CheckTime();
                for (String tid : tellIdsByPids ){
                    //判断当天是否有插入
                    map.put("tid",tid);
                    List<CheckTime> checkByMap = checkMapper.findCheckByMap(map);

                    if (checkByMap.isEmpty()) {
                        //插入
                        checkTime.setId(UUID.randomUUID().toString().replace("-", ""));
                        checkTime.setTid(tid);
                        checkTime.setDate(instance.getTime());
                        if (!isLeaveDay(instance,tid)) {
                            checkTime.setResult("04");
                        }
                        checkTime.setStatus("00");

                        checkMapper.addCheck(checkTime);
                    }

                }
            }
        }
    }

    /**
     *@Author: AndyZhang
     *@Description 每天晚上十一点对当天的考勤进行统计
     *@param
     *@return
     *@Date: 16:13 2021/2/4
     */
    public void endCheck(){
        Calendar instance = Calendar.getInstance();
        //找出当天未签到的考情表
        Map<String,Object> map=new HashMap<>();
        map.put("date",DateUtil.dateToStr(instance.getTime(),DateUtil.FORMAT_DATE_CHECK));
        List<CheckTime> checkByMap = checkMapper.findCheckByMap(map);
        if (checkByMap!=null && !checkByMap.isEmpty()){
            for (CheckTime c:checkByMap) {
                //未签到
                if (c.getStatus().equals("00")){
                    c.setResult("03");
                }
                if (c.getEndTime()==null){
                    c.setResult("05");
                }
                checkMapper.updateCheck(c);
            }
        }
    }

    /**
     *@Author: AndyZhang
     *@Description 每月十号凌晨生成上个月工资账单
     *@param
     *@return
     *@Date: 16:48 2021/2/20
     */
        public void salaryTime() throws Exception{
        //获取当前年月
        Calendar instance = Calendar.getInstance();

        generateSalaryTable(instance);

    }

    /**
     *@Author: AndyZhang
     *@Description 根据时间获取上个月的工资表
     *@param
     *@return
     *@Date: 15:51 2021/2/22
     */
    public  void generateSalaryTable(Calendar instance) throws Exception{
        //设置年月(打印上个月的工资)
        int m = instance.get(Calendar.MONTH);
        int y = instance.get(Calendar.YEAR);
        if (m==0){
            m=12;
            y-=1;
        }
        //查询除董事长所有员工
        List<String> subPids = positionMapper.findSubPids();
        List<String> tellIdsByPids = employeeMapper.findTellIdsByPids(subPids);
        //添加工资条
        for (String tid : tellIdsByPids) {
            //先判断该员工当月工资是否已经生成
            double lateTime = Double.parseDouble(checkService.lateForMonth(tid, y, m));
            double earlyTime = Double.parseDouble(checkService.earlyForMonth(tid, y, m));
            double absenceTime = checkService.absenceForMonth(tid, y, m);
            double leaveTime = checkService.leaveForMonth(tid, y, m);
            //获取该员工职位的工资参数
            PSalaryParam paramByTid = paramMapper.findParamByTid(tid);
            if (paramByTid==null){
                paramByTid=paramMapper.findPsalaryParamById("1");
            }
            Salary salary=new Salary();
            salary.setBasicSalary(paramByTid.getBasicSalary());
            salary.setDate(instance.getTime());
            if (absenceTime==0 && leaveTime==0 && lateTime==0 && earlyTime == 0){
                salary.setFullAttention(paramByTid.getFullAttention());
            }else{
                salary.setFullAttention(0);
            }
            salary.setLateDeduction(lateTime*paramByTid.getLateDeduction());
            salary.setLeaveDeduction(leaveTime*paramByTid.getLeaveDeduction());
            salary.setOtherDeduction(absenceTime*paramByTid.getOtherDeduction());
            salary.setEarlyDeduction(earlyTime*paramByTid.getLateDeduction());
            salary.setOverTimeSalary(0);
            salary.setPositionSalary(paramByTid.getPositionSalary());
            salary.setResult("00");
            salary.setSubsidy(paramByTid.getSubsidy());
            salary.setTid(tid);
            salary.setAbsenceDay(absenceTime);
            salary.setLateTime(lateTime);
            salary.setEarlyTime(earlyTime);
            salary.setLeaveTime(leaveTime);
            salary.setOverTime(0);
            //获取该员工税率和代扣税工资
            KieSession kieSession = kieBase.newKieSession();
            kieSession.insert(salary);
            kieSession.fireAllRules();
            kieSession.dispose();
            log.info("tax:"+salary.getTaxRate());
            double  totalDeduction=salary.getTaxSalary()+salary.getLateDeduction()+salary.getLeaveDeduction()+salary.getEarlyDeduction()+salary.getOtherDeduction();
            double totalPay=salary.getBasicSalary()+salary.getFullAttention()+salary.getOverTimeSalary()+salary.getPositionSalary()+salary.getSubsidy();
            double total=totalPay-totalDeduction;
            salary.setTotalDeduction(totalDeduction);
            salary.setTotalPay(totalPay);
            salary.setTotal(total);
            salaryService.addSalary(salary);
        }
    }



    /**
     *@Author: AndyZhang
     *@Description 判断今天是否为工作日(默认双休)
     *@param
     *@return
     *@Date: 10:46 2021/2/4
     */
//    private boolean isWorkDay(Calendar calendar){
//        boolean d=true;
//        int i = calendar.get(Calendar.DAY_OF_WEEK);
//        if (i == 0 || i == 6 ){
//            d=false;
//        }else{
//            if (isHoliday(calendar)==true){
//                d=false;
//            }
//        }
//        return d;
//    }

    /**
     *@Author: AndyZhang
     *@Description 判断当前日期是否为假期内
     *@param
     *@return
     *@Date: 11:52 2021/2/4
     */
    private boolean isHoliday(Calendar calendar){
        boolean h=false;
        //获取所有有效假期
        Map<String,Object> map=new HashMap<>();
        map.put("status","01");
        List<Holiday> holidayByMap = holidayMapper.findHolidayByMap(map);
        if (holidayByMap!=null && !holidayByMap.isEmpty()){
            for (Holiday holiday: holidayByMap) {
                if (calendar.getTimeInMillis()>= holiday.getStartTime().getTime() && calendar.getTimeInMillis()<=holiday.getEndTime().getTime()){
                    h=true;
                }
            }
        }
        return h;
    }

    /**
     *@Author: AndyZhang
     *@Description 判断某人今天是否请假了
     *@param
     *@return
     *@Date: 16:06 2021/2/20
     */
    private boolean isLeaveDay(Calendar calendar,String tid){
        boolean l=false;
        List<Leave> leaveByResult = leaveMapper.findLeaveByResult("01", tid);
        if (leaveByResult!=null && !leaveByResult.isEmpty()){
            Calendar startTime = Calendar.getInstance();
            Calendar endTime = Calendar.getInstance();
            for (Leave leave : leaveByResult) {
                startTime.setTime(leave.getStartTime());
                endTime.setTime(leave.getEndTime());
                if (calendar.compareTo(startTime)>=0 && calendar.compareTo(endTime)<=0){
                    l=true;
                }
            }
        }
        return l;

    }




    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

            scheduledTaskRegistrar.addTriggerTask(()->{
                    cron1 = scheduleTimeService.getScheduleTimeByCode("startTime").getCron();
                    startCheck();
                    }, triggerContext -> {
                        return new CronTrigger(cron1).nextExecutionTime(triggerContext);
                    }
            );

            scheduledTaskRegistrar.addTriggerTask(()->{
                    cron2 = scheduleTimeService.getScheduleTimeByCode("endTime").getCron();
                    endCheck();
                    }, triggerContext -> {
                        return new CronTrigger(cron2).nextExecutionTime(triggerContext);
                    }
            );

            scheduledTaskRegistrar.addTriggerTask(()->{
                    try {
                         cron3 =  scheduleTimeService.getScheduleTimeByCode("salaryTime").getCron();
                        salaryTime();
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                }, triggerContext -> {
                    return new CronTrigger(cron3).nextExecutionTime(triggerContext);
                }
        );
    }
}
